/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.icee.myth.server.player.state;

import com.icee.myth.common.player.Player;
import com.icee.myth.common.player.state.PlayerState;
import com.icee.myth.common.message.serverMessage.Message;
import com.icee.myth.common.message.serverMessage.Message.MessageType;
import com.icee.myth.config.MapConfig;
import com.icee.myth.server.GameServer;
import com.icee.myth.server.PlayerContext;
import com.icee.myth.server.actor.Human;
import com.icee.myth.server.player.MapPlayer;
import com.icee.myth.protobuf.ExternalCommonProtocol.C2STalkProto;
import com.icee.myth.utils.Consts;
import com.icee.myth.log.GameLogger;
import com.icee.myth.log.message.FileDebugGameLogMessage;
import com.icee.myth.log.message.builder.GameLogMessageBuilder;
import com.icee.myth.protobuf.builder.ClientToMapBuilder;
import com.icee.myth.server.base.occupy.CapeCollinson;
import com.icee.myth.server.base.occupy.OccupyInfo;
import com.icee.myth.server.base.occupy.OccupyInfos;
import com.icee.myth.server.battle.BaseAttackBattle;
import com.icee.myth.server.battle.BaseResistanceBattle;
import com.icee.myth.server.bill.Bill;
import com.icee.myth.server.bill.Coupon;
import com.icee.myth.server.message.serverMessage.BaseAttackBattleResultMessage;
import com.icee.myth.server.message.serverMessage.BaseAttackMessage;
import com.icee.myth.server.message.serverMessage.BaseBarrackDeployMessage;
import com.icee.myth.server.message.serverMessage.BaseCouncilDeployMessage;
import com.icee.myth.server.message.serverMessage.BaseHarvestCapeMineMessage;
import com.icee.myth.server.message.serverMessage.BaseMineDeployMessage;
import com.icee.myth.server.message.serverMessage.BaseOrdnanceDeployMessage;
import com.icee.myth.server.message.serverMessage.BaseResistanceBattleResultMessage;
import com.icee.myth.server.message.serverMessage.BaseResistanceMessage;
import com.icee.myth.server.message.serverMessage.BillResultMessage;
import com.icee.myth.server.message.serverMessage.BuyTokenMessage;
import com.icee.myth.server.message.serverMessage.CardDrawMessage;
import com.icee.myth.server.message.serverMessage.CardSoldMessage;
import com.icee.myth.server.message.serverMessage.CardStrengthenMessage;
import com.icee.myth.server.message.serverMessage.CardTransformMessage;
import com.icee.myth.server.message.serverMessage.ContSignReceiveLivenessRewardMessage;
import com.icee.myth.server.message.serverMessage.ContSignReceiveConsecutiveSignRewardMessage;
import com.icee.myth.server.message.serverMessage.CouponResultMessage;
import com.icee.myth.server.message.serverMessage.EnterActivityStageMessage;
import com.icee.myth.server.message.serverMessage.EnterStageMessage;
import com.icee.myth.server.message.serverMessage.GetCouponMessage;
import com.icee.myth.server.message.serverMessage.GetMailInfoMessage;
import com.icee.myth.server.message.serverMessage.GetNormalActivityItemListMessage;
import com.icee.myth.server.message.serverMessage.GetNormalActivityRewardMessage;
import com.icee.myth.server.message.serverMessage.GetMailRewardMessage;
import com.icee.myth.server.message.serverMessage.GuideNextMessage;
import com.icee.myth.server.message.serverMessage.HegemonyBattleResultMessage;
import com.icee.myth.server.message.serverMessage.HegemonyOneTokenFightMessage;
import com.icee.myth.server.message.serverMessage.HegemonyRefreshMessage;
import com.icee.myth.server.message.serverMessage.HegemonyThreeTokenFightMessage;
import com.icee.myth.server.message.serverMessage.ItemCombineMessage;
import com.icee.myth.server.message.serverMessage.LookOtherPlayerInfoMessage;
import com.icee.myth.server.message.serverMessage.PveBattleResultMessage;
import com.icee.myth.server.message.serverMessage.QuestSubmitMessage;
import com.icee.myth.server.message.serverMessage.RemoveMailMessage;
import com.icee.myth.server.message.serverMessage.SandBoxDeployMessage;
import com.icee.myth.server.message.serverMessage.SocialAddConcernMessage;
import com.icee.myth.server.message.serverMessage.SocialConcernNoteMessage;
import com.icee.myth.server.message.serverMessage.SocialRemoveConcernMessage;
import com.icee.myth.server.message.serverMessage.TalkMessage;
import com.icee.myth.server.message.serverMessage.VipGiftReceiveMessage;
import com.icee.myth.server.message.serverMessage.BaseTrainingDeployMessage;
import com.icee.myth.server.message.serverMessage.GMAddGoldenMessage;
import com.icee.myth.utils.RandomGenerator;
import java.util.LinkedList;

/**
 * NormalState是玩家游戏过程中的一般状态。玩家在游戏过程中可以是一般状态，战斗状态和一组换线状态
 * @author liuxianke
 */
public class NormalPlayerState implements PlayerState {

    public final static NormalPlayerState INSTANCE = new NormalPlayerState();

    private NormalPlayerState() {
    }

    @Override
    public boolean handleMessage(Player player, Message message) {
        MapPlayer p = (MapPlayer) player;
        int playerId = p.getId();
        Human human = p.human;

        MessageType msgType = message.getType();
        switch (msgType) {
            case MAP_GUIDE_NEXT: {
                GuideNextMessage guideNextMessage = (GuideNextMessage) message;
                human.nextGuide(guideNextMessage.curGuildStep);
                return true;
            }
            case MAP_TALK: {
                TalkMessage talkMessage = (TalkMessage) message;
                C2STalkProto talkProto = talkMessage.talkProto;
                String txtMsg = talkProto.getMsg();
                if (txtMsg.length() <= Consts.MAX_TALKMESSAGE_LENGTH) { //消息过长不让发
                    human.talk(talkProto.getChannelType(), txtMsg, talkProto.getPlayerId());
                }
                return true;
            }
            case MAP_START_PVE_BATTLE: {
                human.startPveBattle();
                return true;
            }
            case MAP_PVE_BATTLE_RESULT: {
                PveBattleResultMessage pveBattleResultMessage = (PveBattleResultMessage) message;

                human.receivePveBattleResult(pveBattleResultMessage.stageId, pveBattleResultMessage.battleId, pveBattleResultMessage.rewardItemInfos, pveBattleResultMessage.battleResult);
                return true;
            }
            case MAP_STAGE_CONTINUE: {
                human.stageContinue(true);
                return true;
            }
            case MAP_STAGE_LEAVE: {
                human.leaveStage();
                return true;
            }
            case MAP_STAGE_ENTER: {
                EnterStageMessage enterStageMessage = (EnterStageMessage) message;
                human.enterStage(enterStageMessage.stageId, enterStageMessage.isBigStage, enterStageMessage.helper);
                return true;
            }
            case MAP_STAGE_REVIVE: {
                human.reviveStage();
                return true;
            }
            case MAP_QUEST_SUBMIT: {
                QuestSubmitMessage questSubmitMessage = (QuestSubmitMessage) message;
                human.quests.submit(questSubmitMessage.questId);
                return true;
            }
            case MAP_CONTSIGN_RECEIVE_CUMULATIVE_SIGN_REWARD: {
                human.contSign.receiveCumulativeSignReward();
                return true;
            }
            case MAP_CONTSIGN_RECEIVE_CONSECUTIVE_SIGN_REWARD: {
                ContSignReceiveConsecutiveSignRewardMessage contSignReceiveConsecutiveSignRewardMessage = (ContSignReceiveConsecutiveSignRewardMessage) message;
                human.contSign.receiveConsecutiveSignReward(contSignReceiveConsecutiveSignRewardMessage.day);
                return true;
            }
            case MAP_CONTSIGN_RECEIVE_LIVENESS_REWARD: {
                ContSignReceiveLivenessRewardMessage contSignReceiveLivenessRewardMessage = (ContSignReceiveLivenessRewardMessage) message;
                human.contSign.receiveLivenessReward(contSignReceiveLivenessRewardMessage.index);
                return true;
            }
            case MAP_VIPGIFT_RECEIVE: {
                VipGiftReceiveMessage vipGiftReceiveMessage = (VipGiftReceiveMessage) message;
                human.vipGift.receive(vipGiftReceiveMessage.vip);
                return true;
            }
            case MAP_SANDBOX_DEPLOY: {
                SandBoxDeployMessage sandBoxDeployMessage = (SandBoxDeployMessage) message;
                human.changeSandbox(sandBoxDeployMessage.sandBoxProto);
                return true;
            }
            case MAP_SOCIAL_OTHERPLAYERINFO: {
                LookOtherPlayerInfoMessage lookOtherPlayerInfoMessage = (LookOtherPlayerInfoMessage) message;
                PlayerContext targetPlayerContext = GameServer.INSTANCE.playerContexts.get(lookOtherPlayerInfoMessage.otherPlayerId);
                if (targetPlayerContext != null) {
                    targetPlayerContext.lastVisitTime = GameServer.INSTANCE.getCurrentTime();

                    if (targetPlayerContext.human == null) {
                        // 将本消息缓存下来等待对手数据加载完成
                        targetPlayerContext.addWaitingMessage(message);
                    } else {
                        human.lookOtherPlayerDetailInfo(targetPlayerContext.human);
                    }
                } else {
                    targetPlayerContext = GameServer.INSTANCE.loadPlayerData(lookOtherPlayerInfoMessage.otherPlayerId);

                    assert (targetPlayerContext.human == null);
                    // 将本消息缓存下来等待对手数据加载完成
                    targetPlayerContext.addWaitingMessage(message);
                }
                return true;
            }
            case MAP_SOCIAL_ADD_CONCERN: {
                if (human.relation != null) {
                    human.relation.tryAddConcern(((SocialAddConcernMessage) message).concernId);
                } else {
                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                            "Player[" + human.id + "] can't add concern because relation not inited."));
                }
                return true;
            }
            case MAP_SOCIAL_REMOVE_CONCERN: {
                if (human.relation != null) {
                    human.relation.tryRemoveConcern(((SocialRemoveConcernMessage) message).concernId);
                } else {
                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                            "Player[" + human.id + "] can't remove concern because relation not inited."));
                }
                return true;
            }
            case MAP_SOCIAL_CONCERN_NOTE: {
                if (human.relation != null) {
                    human.relation.sendConcernNote(((SocialConcernNoteMessage) message).targetPlayerId);
                } else {
                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                            "Player[" + human.id + "] can't send concern note because relation not inited."));
                }
                return true;
            }
            case MAP_CARD_STRENGTHEN: {
                CardStrengthenMessage cardStrengthenMessage = (CardStrengthenMessage) message;
                human.cards.strengthen(cardStrengthenMessage.cardInstId, cardStrengthenMessage.foodCardInstIds, true);
                return true;
            }
            case MAP_CARD_TRANSFORM: {
                CardTransformMessage cardTransformMessage = (CardTransformMessage) message;
                human.cards.transform(cardTransformMessage.cardInstId, cardTransformMessage.foodCardInstIds, true);
                return true;
            }
            case MAP_CARD_SOLD: {
                CardSoldMessage cardSoldMessage = (CardSoldMessage) message;
                human.cards.sold(cardSoldMessage.intValuesProto);
                return true;
            }
            case MAP_CARD_DRAW: {
                CardDrawMessage cardDrawMessage = (CardDrawMessage) message;
                human.cards.draw(cardDrawMessage.drawId, cardDrawMessage.drawType, false);
                return true;
            }
            case MAP_BUY_ENERGY: {
                human.buyEnergy();
                return true;
            }
            case MAP_BUY_TOKEN: {
                BuyTokenMessage buyTokenMessage = (BuyTokenMessage) message;
                human.buyToken(buyTokenMessage.num);
                return true;
            }
            case MAP_ITEM_COMBINE: {
                ItemCombineMessage itemCombineMessage = (ItemCombineMessage) message;
                human.items.combine(itemCombineMessage.itemId);
                return true;
            }
            case MAP_BILL_RESULT: {
                BillResultMessage billResultMessage = (BillResultMessage) message;
                human.increaseGold1(billResultMessage.passport, billResultMessage.order, billResultMessage.status);
                return true;
            }
            case MAP_COUPON_RESULT: {
                CouponResultMessage couponResultMessage = (CouponResultMessage) message;
                human.addCouponReward(couponResultMessage.code, couponResultMessage.reward);
                return true;
            }
            // 收到充值通知或玩家刷新充值通知，执行充值获取
            case MAP_BILLNOTIFY:
            case MAP_GET_BILL: {
                GameServer.INSTANCE.executeBill(new Bill(human.id, human.mapPlayer.passport));
                return true;
            }
            case MAP_GET_COUPON: {
                GameServer.INSTANCE.executeCoupon(new Coupon(human, p.passport, ((GetCouponMessage) message).couponCode));
                return true;
            }
            case MAP_MAIL_GET_LIST: {
                human.mails.getList();
                return true;
            }
            case MAP_MAIL_GET_INFO: {
                GetMailInfoMessage getMailInfoMessage = (GetMailInfoMessage) message;

                human.mails.getMailInfo(getMailInfoMessage.mailId);
                return true;
            }
            case MAP_MAIL_GET_REWARD: {
                GetMailRewardMessage getMailRewardMessage = (GetMailRewardMessage) message;

                human.mails.getReward(getMailRewardMessage.mailId);
                return true;
            }
            case MAP_MAIL_REMOVE: {
                RemoveMailMessage removeMailMessage = (RemoveMailMessage) message;

                human.mails.removeMail(removeMailMessage.mailId);
                return true;
            }
            case MAP_NORMAL_ACTIVITY_GET_LIST: {
                human.normalActivity.getActivityList();
                return true;
            }
            case MAP_NORMAL_ACTIVITY_GET_ITEM_LIST: {
                GetNormalActivityItemListMessage getNormalActivityItemListMessage = (GetNormalActivityItemListMessage) message;
                human.normalActivity.getActivityItemList(getNormalActivityItemListMessage.activityId);
                return true;
            }
            case MAP_NORMAL_ACTIVITY_ENTER_STAGE: {
                EnterActivityStageMessage enterActivityStageMessage = (EnterActivityStageMessage) message;
                human.normalActivity.enterActivityStage(enterActivityStageMessage.activityId, enterActivityStageMessage.itemId, enterActivityStageMessage.helperId);
                return true;
            }
            case MAP_GET_NORMAL_ACTIVITY_REWARD: {
                GetNormalActivityRewardMessage getNormalActivityRewardMessage = (GetNormalActivityRewardMessage) message;

                human.normalActivity.getReward(getNormalActivityRewardMessage.activityId, getNormalActivityRewardMessage.itemId);
                return true;
            }
            case MAP_CARD_DRAW_ACTIVITY_GET_LIST: {
                human.getCardDrawActivityList();
                return true;
            }
            case MAP_STAGE_ACTIVITY_GET_LIST: {
                human.getStageActivityList();
                return true;
            }
            case MAP_HEGEMONY_ONE_TOKEN_FIGHT: {
                HegemonyOneTokenFightMessage hegemonyOneTokenFightMessage = (HegemonyOneTokenFightMessage) message;

                human.striveForHegemony(hegemonyOneTokenFightMessage.targetSlot, false);
                return true;
            }
            case MAP_HEGEMONY_THREE_TOKEN_FIGHT: {
                HegemonyThreeTokenFightMessage hegemonyThreeTokenFightMessage = (HegemonyThreeTokenFightMessage) message;

                human.striveForHegemony(hegemonyThreeTokenFightMessage.targetSlot, true);
                return true;
            }
            case MAP_HEGEMONY_BATTLERESULT: {
                HegemonyBattleResultMessage hegemonyBattleResultMessage = (HegemonyBattleResultMessage) message;

                human.receiveHegemonyBattleResult(hegemonyBattleResultMessage.targetSlot, hegemonyBattleResultMessage.targetPower, hegemonyBattleResultMessage.stimulate, hegemonyBattleResultMessage.battleResult);
                return true;
            }
            case MAP_HEGEMONY_REFRESH: {
                HegemonyRefreshMessage hegemonyRefreshMessage = (HegemonyRefreshMessage) message;

                human.refreshHegemony(hegemonyRefreshMessage.count);
                return true;
            }
            case MAP_HEGEMONY_GET_PAY: {
                human.getHegemonyPay();
                return true;
            }
            case MAP_BASE_BARRACK_DEPLOY: {
                BaseBarrackDeployMessage baseBarrackDeployMessage = (BaseBarrackDeployMessage) message;
                human.changeBarrack(baseBarrackDeployMessage.intValuesProto);
                return true;
            }
            case MAP_BASE_ORDNANCE_DEPLOY: {
                BaseOrdnanceDeployMessage baseOrdnanceDeployMessage = (BaseOrdnanceDeployMessage) message;
                human.changeOrdnance(baseOrdnanceDeployMessage.intValuesProto);
                return true;
            }
            case MAP_BASE_COUNCIL_DEPLOY: {
                BaseCouncilDeployMessage baseCouncilDeployMessage = (BaseCouncilDeployMessage) message;
                human.changeCouncil(baseCouncilDeployMessage.intValuesProto);
                return true;
            }
            case MAP_BASE_TRAINING_DEPLOY: {
                BaseTrainingDeployMessage baseTrainingDeployMessage = (BaseTrainingDeployMessage) message;
                human.changeTraining(baseTrainingDeployMessage.intValuesProto);
                return true;
            }
            case MAP_BASE_MINE_DEPLOY: {
                if (human.lv >= MapConfig.INSTANCE.openMineLevel) {
                    OccupyInfo selfOccupyInfo = OccupyInfos.INSTANCE.tryGetOccupyInfo(playerId, message);
                    if (selfOccupyInfo != null) {
                        // 部署银矿
                        if (human.mine.change(((BaseMineDeployMessage) message).intValuesProto)) {
                            // 先计算换卡之前的收获
                            selfOccupyInfo.refreshSilver();

                            // 修改银矿产量数据
                            selfOccupyInfo.production = human.mine.getProduction();

                            OccupyInfos.INSTANCE.setNeedSave(selfOccupyInfo);
                        }
                    }
                } else {
                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                            "Player[" + playerId + "] can't deploy mine because level limit."));
                }

                return true;
            }
            case MAP_BASE_GET_MINE_INCOME_INFO: {
                if (human.lv >= MapConfig.INSTANCE.openMineLevel) {
                    OccupyInfo selfOccupyInfo = OccupyInfos.INSTANCE.tryGetOccupyInfo(playerId, message);
                    if (selfOccupyInfo != null) {
                        selfOccupyInfo.refreshSilver();
                        human.sendMessage(ClientToMapBuilder.buildMineIncomeInfo(selfOccupyInfo));
                    }
                } else {
                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                            "Player[" + playerId + "] can't get mine income info because level limit."));
                }

                return true;
            }
            case MAP_BASE_HARVEST_SELF_MINE: {
                if (human.lv >= MapConfig.INSTANCE.openMineLevel) {
                    OccupyInfo selfOccupyInfo = OccupyInfos.INSTANCE.tryGetOccupyInfo(playerId, message);
                    if (selfOccupyInfo != null) {
                        // 刷新自己收获（即自己的银矿产出）
                        selfOccupyInfo.refreshSilver();

                        // 消化银矿产出
                        if (selfOccupyInfo.silver > 0) {
                            human.increaseSilver(selfOccupyInfo.silver, Consts.SOUL_CHANGE_LOG_TYPE_HARVEST_SELF_MINE, Consts.SOUL_CHANGE_LOG_SUBTYPE_NONE, true);

                            // 计算是否产出黄金
                            int goldProbability = selfOccupyInfo.silver / 500000;
                            if (RandomGenerator.INSTANCE.generator.nextInt(100) < goldProbability) {
                                human.increaseGold(0, 10, Consts.SOUL_CHANGE_LOG_TYPE_HARVEST_SELF_MINE, Consts.SOUL_CHANGE_LOG_SUBTYPE_NONE, true);
                            }

                            selfOccupyInfo.silver = 0;
                            selfOccupyInfo.lastHarvestTime = GameServer.INSTANCE.getCurrentTime();
                            OccupyInfos.INSTANCE.setNeedSave(selfOccupyInfo);
                            human.sendMessage(ClientToMapBuilder.buildMineIncomeInfo(selfOccupyInfo));
                        }
                    }
                } else {
                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                            "Player[" + playerId + "] can't harvest self mine because level limit."));
                }

                return true;
            }
            case MAP_BASE_HARVEST_CAPE_MINE: {
                if (human.lv >= MapConfig.INSTANCE.openMineLevel) {
                    OccupyInfo selfOccupyInfo = OccupyInfos.INSTANCE.tryGetOccupyInfo(playerId, message);
                    if (selfOccupyInfo != null) {
                        BaseHarvestCapeMineMessage baseHarvestCapeMineMessage = (BaseHarvestCapeMineMessage) message;
                        CapeCollinson capeCollinson = selfOccupyInfo.getCapeCollinson(baseHarvestCapeMineMessage.capeId);

                        if (capeCollinson != null) {
                            OccupyInfo capeOccupyInfo = null;
                            if (!capeCollinson.isFree()) {
                                capeOccupyInfo = OccupyInfos.INSTANCE.tryGetOccupyInfo(capeCollinson.id, message);

                                if (capeOccupyInfo == null) {
                                    return true;
                                }

                                // 解除臣属关系
                                OccupyInfo.setFree(capeOccupyInfo, selfOccupyInfo);
                            }

                            // 收获并从臣属列表中删除此臣属（取消君臣关系）
                            // 计算收获
                            int silver = 0;
                            if (capeCollinson.freeTime == 0) {
                                long currentTime = GameServer.INSTANCE.getCurrentTime();
                                if (currentTime < capeCollinson.startTime + MapConfig.INSTANCE.maxOccupyTime) {
                                    silver = (int) (capeCollinson.production * MapConfig.INSTANCE.mineTaxRatio) * (int) ((currentTime - capeCollinson.startTime) / MapConfig.INSTANCE.minePeriod);
                                } else {
                                    silver = (int) (capeCollinson.production * MapConfig.INSTANCE.mineTaxRatio) * (MapConfig.INSTANCE.maxOccupyTime / MapConfig.INSTANCE.minePeriod);
                                }
                            } else {
                                silver = (int) (capeCollinson.production * MapConfig.INSTANCE.mineTaxRatio) * (int) ((capeCollinson.freeTime - capeCollinson.startTime) / MapConfig.INSTANCE.minePeriod);
                            }

                            if (silver > 0) {
                                human.increaseSilver(silver, Consts.SOUL_CHANGE_LOG_TYPE_HARVEST_CAPE_MINE, capeCollinson.id, true);
                            }

                            selfOccupyInfo.capeCollinsons.remove(capeCollinson);
                            OccupyInfos.INSTANCE.setNeedSave(selfOccupyInfo);
                            
                            human.sendMessage(ClientToMapBuilder.buildRemoveCapecollinson(capeCollinson.id));
                        } else {
                            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                    "Human[" + playerId + "] can't harvest capecollinson[" + baseHarvestCapeMineMessage.capeId + "] because not capecollinson."));
                        }
                    }
                } else {
                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                            "Player[" + playerId + "] can't harvest cape mine because level limit."));
                }
                
                return true;
            }
            case MAP_BASE_GET_OCCUPY_INFO: {
                if (human.lv >= MapConfig.INSTANCE.openMineLevel) {
                    OccupyInfo selfOccupyInfo = OccupyInfos.INSTANCE.tryGetOccupyInfo(playerId, message);
                    if (selfOccupyInfo != null) {
                        selfOccupyInfo.refreshSilver();

                        OccupyInfo kingOccupyInfo = (selfOccupyInfo.king != null)?OccupyInfos.INSTANCE.tryGetOccupyInfo(selfOccupyInfo.king.id, message):null;
                        if ((selfOccupyInfo.king == null) || (kingOccupyInfo != null)) {
                            // 确认臣属的臣属数据在内存
                            LinkedList<OccupyInfo> capeOccupyInfos = null;
                            if (selfOccupyInfo.capeCollinsons != null) {
                                capeOccupyInfos = new LinkedList<OccupyInfo>();
                                for (CapeCollinson capeCollinson : selfOccupyInfo.capeCollinsons) {
                                    OccupyInfo capeOccupyInfo = OccupyInfos.INSTANCE.tryGetOccupyInfo(capeCollinson.id, message);

                                    if (capeOccupyInfo == null) {
                                        return true;
                                    }

                                    // 校验数据一致性，若不一致，打印错误消息（强制关机会导致数据不一致）
                                    if (((capeOccupyInfo.king == null) || (capeOccupyInfo.king.id != playerId)) && !capeCollinson.isFree()) {
                                        GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                                FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                                "Occupy info inconsistency between king[" + playerId + "] and capecollinson[" + capeCollinson.id + "]."));
                                        capeCollinson.freeTime = GameServer.INSTANCE.getCurrentTime();
                                        OccupyInfos.INSTANCE.setNeedSave(selfOccupyInfo);
                                    }

                                    capeOccupyInfos.add(capeOccupyInfo);
                                }
                            }

                            // 回传玩家大帐信息
                            human.sendMessage(ClientToMapBuilder.buildOccupyInfo(selfOccupyInfo, kingOccupyInfo, capeOccupyInfos));
                        }
                    }
                } else {
                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                            "Player[" + playerId + "] can't get occupy info because level limit."));
                }

                return true;
            }
            case MAP_BASE_GET_TARGETS: {
                if (human.lv >= MapConfig.INSTANCE.openMineLevel) {
                    OccupyInfo selfOccupyInfo = OccupyInfos.INSTANCE.tryGetOccupyInfo(playerId, message);
                    if (selfOccupyInfo != null) {
                        human.getBaseTargets();
                    }
                } else {
                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                            "Player[" + playerId + "] can't get base targets because level limit."));
                }

                return true;
            }
            case MAP_BASE_ATTACK: {
                if (human.lv >= MapConfig.INSTANCE.openMineLevel) {
                    BaseAttackMessage baseAttackMessage = (BaseAttackMessage) message;
                    if (human.token > 0) {
                        // 先确认目标合法
                        if (human.baseTargets != null) {
                            if (human.baseTargets.fightingOccupyInfo == null) {
                                if (human.baseTargets.isTargetCorrect(baseAttackMessage.targetIndex, baseAttackMessage.targetId)) {
                                    OccupyInfo selfOccupyInfo = OccupyInfos.INSTANCE.tryGetOccupyInfo(playerId, message);
                                    if (selfOccupyInfo != null) {
                                        if ((selfOccupyInfo.capeCollinsons == null) || (selfOccupyInfo.capeCollinsons.size() < Consts.MAX_CAPECOLLINSON_NUM)) {
                                            OccupyInfo targetOccupyInfo = OccupyInfos.INSTANCE.tryGetOccupyInfo(baseAttackMessage.targetId, message);

                                            if (targetOccupyInfo != null) {
                                                if (!targetOccupyInfo.fighting) {
                                                    // 刷新目标银矿产出
                                                    targetOccupyInfo.refreshSilver();
                                                    // 确认实际目标，若目标有君主需要与目标君主部队交战，否则与目标部队交战
                                                    int realTargetId = baseAttackMessage.targetId;
                                                    if (targetOccupyInfo.king != null) {
                                                        realTargetId = targetOccupyInfo.king.id;
                                                    }

                                                    // 找到目标对象
                                                    PlayerContext targetPlayerContext = GameServer.INSTANCE.playerContexts.get(realTargetId);
                                                    if (targetPlayerContext != null) {
                                                        targetPlayerContext.lastVisitTime = GameServer.INSTANCE.getCurrentTime();

                                                        Human targetHuman = targetPlayerContext.human;
                                                        if (targetHuman == null) {
                                                            // 将本挑战消息缓存下来等待对手数据加载完成
                                                            targetPlayerContext.addWaitingMessage(message);
                                                        } else {
                                                            human.decreaseToken(1, true);

                                                            // 与目标交战
                                                            // 产生战斗
                                                            BaseAttackBattle baseAttackBattle = human.createBaseAttackBattle(baseAttackMessage.targetIndex, baseAttackMessage.targetId, targetHuman);

                                                            GameServer.INSTANCE.executeBattle(baseAttackBattle);

                                                            targetOccupyInfo.fighting = true;
                                                            human.baseTargets.fightingOccupyInfo = targetOccupyInfo;
                                                        }
                                                    } else {
                                                        targetPlayerContext = GameServer.INSTANCE.loadPlayerData(realTargetId);

                                                        assert (targetPlayerContext.human == null);
                                                        // 将本挑战消息缓存下来等待对手数据加载完成
                                                        targetPlayerContext.addWaitingMessage(message);
                                                    }
                                                } else {
                                                    targetOccupyInfo.addWaitingMessage(message);
                                                }
                                            }
                                        } else {
                                            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                                    "Player[" + playerId + "] can't base attack because capecollinson list is full"));
                                        }
                                    }
                                } else {
                                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                            "Player[" + playerId + "] can't base attack because target not correct"));
                                }
                            } else {
                                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                        "Player[" + playerId + "] can't base attack because is attacking."));
                            }
                        } else {
                            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                    "Player[" + playerId + "] can't base attack because no targets."));
                        }
                    } else {
                        GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                "Player[" + playerId + "] can't base attack because not enough token."));
                    }
                } else {
                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                            "Player[" + playerId + "] can't base attack because level limit."));
                }

                return true;
            }
            case MAP_BASE_ATTACK_BATTLERESULT: {
                if (human.lv >= MapConfig.INSTANCE.openMineLevel) {
                    // 先确认目标合法
                    BaseAttackBattleResultMessage baseAttackBattleResultMessage = (BaseAttackBattleResultMessage) message;
                    if (human.baseTargets != null) {
                        if (human.baseTargets.fightingOccupyInfo != null) {
                            if (human.baseTargets.fightingOccupyInfo.id == baseAttackBattleResultMessage.targetId) {
                                if (human.baseTargets.isTargetCorrect(baseAttackBattleResultMessage.targetIndex, baseAttackBattleResultMessage.targetId)) {
                                    OccupyInfo selfOccupyInfo = OccupyInfos.INSTANCE.tryGetOccupyInfo(playerId, message);
                                    if (selfOccupyInfo != null) {
                                        if ((selfOccupyInfo.capeCollinsons == null) || (selfOccupyInfo.capeCollinsons.size() < Consts.MAX_CAPECOLLINSON_NUM)) {
                                            OccupyInfo targetOccupyInfo = OccupyInfos.INSTANCE.getOccupyInfo(baseAttackBattleResultMessage.targetId);

                                            if (targetOccupyInfo == human.baseTargets.fightingOccupyInfo) {
                                                if (targetOccupyInfo.fighting) {
                                                    // 若胜利，则修改相关臣属关系
                                                    if (baseAttackBattleResultMessage.battleResult.getWinner() == 0) {
                                                        // 若目标有君主，修改将其君主的臣属列表中的目标臣属状态设为脱离
                                                        if (targetOccupyInfo.king != null) {
                                                            // 脱离与原君主的臣属关系
                                                            OccupyInfo targetKingOccupyInfo = OccupyInfos.INSTANCE.tryGetOccupyInfo(targetOccupyInfo.king.id, message);

                                                            if (targetKingOccupyInfo == null) {
                                                                return true;
                                                            }

                                                            OccupyInfo.setFree(targetOccupyInfo, targetKingOccupyInfo);
                                                        }

                                                        // 建立臣属关系
                                                        CapeCollinson capeCollinson = OccupyInfo.occupy(targetOccupyInfo, selfOccupyInfo);

                                                        // 发送战斗结果给客户端
                                                        human.sendMessage(ClientToMapBuilder.buildBaseAttackBattleResult(baseAttackBattleResultMessage.battleResult));

                                                        // 通知客户端
                                                        human.sendMessage(ClientToMapBuilder.buildBaseAddCapeCollinson(targetOccupyInfo, capeCollinson));
                                                    } else {
                                                        // 发送战斗结果给客户端
                                                        human.sendMessage(ClientToMapBuilder.buildBaseAttackBattleResult(baseAttackBattleResultMessage.battleResult));
                                                    }

                                                    targetOccupyInfo.fighting = false;
                                                    human.baseTargets.fightingOccupyInfo = null;

                                                    // 清除据点目标
                                                    human.baseTargets = null;

                                                    // 将等待的消息重新加入消息队列
                                                    targetOccupyInfo.waitUpWaitingMessage();
                                                } else {
                                                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                                            "Player[" + playerId + "] receive base attack battle result but target is not fighting"));
                                                }
                                            } else {
                                                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                                        "Player[" + playerId + "] receive base attack battle result but target occupy info changed"));
                                            }
                                        } else {
                                            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                                    "Player[" + playerId + "] receive base attack battle result but capecollinson list is full"));
                                        }
                                    }
                                } else {
                                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                            "Player[" + playerId + "] receive base attack battle result but target not correct"));
                                }
                            } else {
                                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                        "Player[" + playerId + "] receive base attack battle result but not the waiting target."));
                            }
                        } else {
                            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                    "Player[" + playerId + "] receive base attack battle result when not fighting."));
                        }
                    } else {
                        GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                "Player[" + playerId + "] receive base attack battle result when no targets."));
                    }
                } else {
                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                            "Player[" + playerId + "] receive base attack battle result when level limit."));
                }

                return true;
            }
            case MAP_BASE_RESISTANCE: {
                if (human.lv >= MapConfig.INSTANCE.openMineLevel) {
                    BaseResistanceMessage baseResistanceMessage = (BaseResistanceMessage) message;
                    if (human.token >= (baseResistanceMessage.stimulate?3:1)) {  // 判断军令是否足够
                        if (human.selfOccupyInfo == null) { // 判断是否在反抗中
                            OccupyInfo selfOccupyInfo = OccupyInfos.INSTANCE.tryGetOccupyInfo(playerId, message);
                            if (selfOccupyInfo != null) {
                                if (selfOccupyInfo.king != null) {
                                    if (!selfOccupyInfo.fighting) {
                                        selfOccupyInfo.refreshSilver();
                                        if (selfOccupyInfo.king != null) {
                                            OccupyInfo kingOccupyInfo = OccupyInfos.INSTANCE.tryGetOccupyInfo(selfOccupyInfo.king.id, message);
                                            if (kingOccupyInfo != null) {
                                                CapeCollinson capeCollinson = kingOccupyInfo.getCapeCollinson(playerId);
                                                if (capeCollinson != null) {
                                                    // 确认君主数据在内存
                                                    PlayerContext targetPlayerContext = GameServer.INSTANCE.playerContexts.get(selfOccupyInfo.king.id);
                                                    if (targetPlayerContext != null) {
                                                        targetPlayerContext.lastVisitTime = GameServer.INSTANCE.getCurrentTime();

                                                        Human targetHuman = targetPlayerContext.human;
                                                        if (targetHuman == null) {
                                                            // 将本挑战消息缓存下来等待对手数据加载完成
                                                            targetPlayerContext.addWaitingMessage(message);
                                                        } else {
                                                            // 扣军令
                                                            if (baseResistanceMessage.stimulate) {
                                                                human.decreaseToken(3, true);
                                                            } else {
                                                                human.decreaseToken(1, true);
                                                            }

                                                            // 与目标交战
                                                            // 产生战斗
                                                            BaseResistanceBattle baseResistanceBattle = human.createBaseResistanceBattle(selfOccupyInfo.king.id, targetHuman, baseResistanceMessage.stimulate);

                                                            GameServer.INSTANCE.executeBattle(baseResistanceBattle);

                                                            selfOccupyInfo.fighting = true;
                                                            human.selfOccupyInfo = selfOccupyInfo;
                                                        }
                                                    } else {
                                                        targetPlayerContext = GameServer.INSTANCE.loadPlayerData(selfOccupyInfo.king.id);

                                                        assert (targetPlayerContext.human == null);
                                                        // 将本挑战消息缓存下来等待对手数据加载完成
                                                        targetPlayerContext.addWaitingMessage(message);
                                                    }
                                                } else {
                                                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                                            "Player[" + playerId + "] can't resistance when not in king[" + selfOccupyInfo.king + "]'s capecollinson list."));
                                                    selfOccupyInfo.king = null;
                                                    OccupyInfos.INSTANCE.setNeedSave(selfOccupyInfo);
                                                }
                                            }
                                        } else {
                                            // 直接通知客户端自由
                                            human.sendMessage(ClientToMapBuilder.buildBaseFree());
                                        }
                                    } else {
                                        selfOccupyInfo.addWaitingMessage(message);
                                    }
                                } else {
                                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                            "Player[" + playerId + "] can't resistance when no king."));

                                    // 直接通知客户端自由
                                    human.sendMessage(ClientToMapBuilder.buildBaseFree());
                                }
                            }
                        } else {
                            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                    "Player[" + playerId + "] can't resistance because is resistancing."));
                        }
                    } else {
                        GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                "Player[" + playerId + "] can't resistance because no token."));
                    }
                } else {
                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                            "Player[" + playerId + "] can't resistance because level limit."));
                }

                return true;
            }
            case MAP_BASE_RESISTANCE_BATTLERESULT: {
                if (human.lv >= MapConfig.INSTANCE.openMineLevel) {
                    // 先确认目标合法
                    BaseResistanceBattleResultMessage baseResistanceBattleResultMessage = (BaseResistanceBattleResultMessage) message;
                    if (human.selfOccupyInfo != null) {
                        if (human.selfOccupyInfo.fighting) {
                            if ((human.selfOccupyInfo.king != null) && (human.selfOccupyInfo.king.id == baseResistanceBattleResultMessage.king)) {
                                OccupyInfo selfOccupyInfo = OccupyInfos.INSTANCE.getOccupyInfo(playerId);
                                if (selfOccupyInfo == human.selfOccupyInfo) {
                                    OccupyInfo kingOccupyInfo = OccupyInfos.INSTANCE.tryGetOccupyInfo(selfOccupyInfo.king.id, message);
                                    if (kingOccupyInfo != null) {
                                        CapeCollinson capeCollinson = kingOccupyInfo.getCapeCollinson(playerId);
                                        if (capeCollinson != null) {
                                            // 若胜利，则修改相关臣属关系
                                            if (baseResistanceBattleResultMessage.battleResult.getWinner() == 0) {
                                                // 战斗胜利
                                                // 脱离臣属关系
                                                OccupyInfo.setFree(selfOccupyInfo, kingOccupyInfo);

                                                // 发送战斗结果给客户端
                                                human.sendMessage(ClientToMapBuilder.buildBaseResistanceBattleResult(baseResistanceBattleResultMessage.battleResult, baseResistanceBattleResultMessage.stimulate));

                                                // 发送自由消息
                                                human.sendMessage(ClientToMapBuilder.buildBaseFree());
                                            } else {
                                                // 战斗失败
                                                // 发送战斗结果给客户端
                                                human.sendMessage(ClientToMapBuilder.buildBaseResistanceBattleResult(baseResistanceBattleResultMessage.battleResult, baseResistanceBattleResultMessage.stimulate));
                                            }

                                            human.selfOccupyInfo = null;
                                            selfOccupyInfo.fighting = false;

                                            // 将等待的消息重新加入消息队列
                                            selfOccupyInfo.waitUpWaitingMessage();
                                        } else {
                                            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                                    "Player[" + playerId + "] receive base resistance battle result but not in king[" + selfOccupyInfo.king + "]'s capecollinson list."));
                                            selfOccupyInfo.king = null;
                                            OccupyInfos.INSTANCE.setNeedSave(selfOccupyInfo);
                                        }
                                    }
                                } else {
                                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                            "Player[" + playerId + "] receive base resistance battle result but self occupy info not correct."));
                                }
                            } else {
                                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                        "Player[" + playerId + "] receive base resistance battle result but not the waiting target."));

                                human.selfOccupyInfo.fighting = false;
                                // 将等待的消息重新加入消息队列
                                human.selfOccupyInfo.waitUpWaitingMessage();
                                
                                human.selfOccupyInfo = null;
                                
                                // TODO: 是否需要通知客户端君主改变？
                            }
                        } else {
                            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                    "Player[" + playerId + "] receive base resistance battle result when not fighting."));
                        }
                    } else {
                        GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                "Player[" + playerId + "] receive base resistance battle result when not resistancing."));
                    }
                } else {
                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                            "Player[" + playerId + "] receive base resistance battle result when level limit."));
                }
                return true;
            }
            case MAP_GM_ADD_ENERGY: {
                human.increaseEnergyGM();
                return true;
            }
            case MAP_GM_IGNORE_GUIDE_STEP: {
                human.ignoreGuideStep();
                return true;
            }
            case MAP_GM_ADD_GOLDEN: {
                GMAddGoldenMessage gmAddGoldenMessage = (GMAddGoldenMessage)message;
                human.increaseGold(gmAddGoldenMessage.num, 0, Consts.SOUL_CHANGE_LOG_TYPE_GM_INCREASE_YELLOWSOUL1, Consts.SOUL_CHANGE_LOG_SUBTYPE_NONE, human.inGame);
            }
            default: {
                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                        "NormalPlayerState -- Player[" + playerId + "] can't handle message[" + msgType + "]."));
                return false;
            }
        }
    }
}
